#include "stdafx.h"
#include "Parser.h"
#include "ColumnNames.h"
#include "RowNames.h"

CParser::CParser(CScanner & scanner, CCodeGeneratorManager & codeGeneratorManager)
	:m_scanner(scanner), m_characterTableChecker(CCharacterTableChecker(m_scanner, m_characterTable)), m_codeGeneratorManager(codeGeneratorManager), m_tableParsing(CTableParsing(scanner))
{
    InitConvolutions();
}

void CParser::Parse(bool isFirstParse)
{
	m_isFirstParse = isFirstParse;
	m_scanner.Reset();
	m_characterTableChecker.Reset();
	
	if (!m_isFirstParse)
	{
		m_codeGeneratorManager.SetChecker(&m_characterTableChecker);
	}

	std::string prevColumnName = "";
	std::string currColumnName = m_tokenManager.TokenToString(m_scanner.GetNextToken());
    CRow currRow = m_tableParsing.GetRow(0);
    m_rowsStack.push(currRow);
    while (true)
    {
        std::string rowName = currRow.GetNextRowName(currColumnName);
        if (rowName == "ok")
        {
			if (m_isFirstParse)
			{
				std::cout << "correct" << std::endl;
			}
            return;
        }
		if (m_isFirstParse)
		{
			if (rowName == "")
			{
				stringstream errorMsg;
				errorMsg <<  "Syntax error. Recheck code at line " << m_scanner.GetCurrLineIndex() << "!" << endl;

				throw domain_error(errorMsg.str());
			}
		}
        if (!IsMember(rowName))
        {
            currRow = m_tableParsing.GetRow(rowName);
            m_rowsStack.push(currRow);
            if (prevColumnName == "")
            {
				currColumnName = m_tokenManager.TokenToString(m_scanner.GetNextToken());
            }
            else
            {
                currColumnName = prevColumnName;
                prevColumnName = "";
            }
			if (!m_isFirstParse)
			{
				m_codeGeneratorManager.SetCurrRowName(currRow.GetRowName());
			}
        }
        else
        {
            prevColumnName = currColumnName;
            currColumnName = (this->*m_convolutions[rowName])();
			currRow = m_rowsStack.top();
        }

		m_isFirstParse ? m_characterTableChecker.AddToCharacterTable(currRow.GetRowName()) 
					 : m_characterTableChecker.CheckCharacters(currRow.GetRowName(), currColumnName);
    }
}

void CParser::InitConvolutions()
{
    m_convolutions.insert(std::pair<std::string, std::string(CParser::*)()>("R2", &CParser::R2));
    m_convolutions.insert(std::pair<std::string, std::string(CParser::*)()>("R3", &CParser::R3));
    m_convolutions.insert(std::pair<std::string, std::string(CParser::*)()>("R4", &CParser::R4));
    m_convolutions.insert(std::pair<std::string, std::string(CParser::*)()>("R5", &CParser::R5));
    m_convolutions.insert(std::pair<std::string, std::string(CParser::*)()>("R6", &CParser::R6));
    m_convolutions.insert(std::pair<std::string, std::string(CParser::*)()>("R7", &CParser::R7));
    m_convolutions.insert(std::pair<std::string, std::string(CParser::*)()>("R8", &CParser::R8));
    m_convolutions.insert(std::pair<std::string, std::string(CParser::*)()>("R9", &CParser::R9));
    m_convolutions.insert(std::pair<std::string, std::string(CParser::*)()>("R10", &CParser::R10));
    m_convolutions.insert(std::pair<std::string, std::string(CParser::*)()>("R11", &CParser::R11));
    m_convolutions.insert(std::pair<std::string, std::string(CParser::*)()>("R12", &CParser::R12));
    m_convolutions.insert(std::pair<std::string, std::string(CParser::*)()>("R13", &CParser::R13));
    m_convolutions.insert(std::pair<std::string, std::string(CParser::*)()>("R14", &CParser::R14));
    m_convolutions.insert(std::pair<std::string, std::string(CParser::*)()>("R15", &CParser::R15));
    m_convolutions.insert(std::pair<std::string, std::string(CParser::*)()>("R16", &CParser::R16));
    m_convolutions.insert(std::pair<std::string, std::string(CParser::*)()>("R17", &CParser::R17));
    m_convolutions.insert(std::pair<std::string, std::string(CParser::*)()>("R18", &CParser::R18));
    m_convolutions.insert(std::pair<std::string, std::string(CParser::*)()>("R19", &CParser::R19));
    m_convolutions.insert(std::pair<std::string, std::string(CParser::*)()>("R20", &CParser::R20));
    m_convolutions.insert(std::pair<std::string, std::string(CParser::*)()>("R21", &CParser::R21));
    m_convolutions.insert(std::pair<std::string, std::string(CParser::*)()>("R22", &CParser::R22));
    m_convolutions.insert(std::pair<std::string, std::string(CParser::*)()>("R23", &CParser::R23));
    m_convolutions.insert(std::pair<std::string, std::string(CParser::*)()>("R24", &CParser::R24));
    m_convolutions.insert(std::pair<std::string, std::string(CParser::*)()>("R25", &CParser::R25));
    m_convolutions.insert(std::pair<std::string, std::string(CParser::*)()>("R26", &CParser::R26));
    m_convolutions.insert(std::pair<std::string, std::string(CParser::*)()>("R27", &CParser::R27));
    m_convolutions.insert(std::pair<std::string, std::string(CParser::*)()>("R28", &CParser::R28));
    m_convolutions.insert(std::pair<std::string, std::string(CParser::*)()>("R29", &CParser::R29));
    m_convolutions.insert(std::pair<std::string, std::string(CParser::*)()>("R30", &CParser::R30));
    m_convolutions.insert(std::pair<std::string, std::string(CParser::*)()>("R31", &CParser::R31));
    m_convolutions.insert(std::pair<std::string, std::string(CParser::*)()>("R32", &CParser::R32));
    m_convolutions.insert(std::pair<std::string, std::string(CParser::*)()>("R33", &CParser::R33));
    m_convolutions.insert(std::pair<std::string, std::string(CParser::*)()>("R34", &CParser::R34));
    m_convolutions.insert(std::pair<std::string, std::string(CParser::*)()>("R35", &CParser::R35));
    m_convolutions.insert(std::pair<std::string, std::string(CParser::*)()>("R36", &CParser::R36));
    m_convolutions.insert(std::pair<std::string, std::string(CParser::*)()>("R37", &CParser::R37));
    m_convolutions.insert(std::pair<std::string, std::string(CParser::*)()>("R38", &CParser::R38));
    m_convolutions.insert(std::pair<std::string, std::string(CParser::*)()>("R39", &CParser::R39));
    m_convolutions.insert(std::pair<std::string, std::string(CParser::*)()>("R40", &CParser::R40));
    m_convolutions.insert(std::pair<std::string, std::string(CParser::*)()>("R41", &CParser::R41));
    m_convolutions.insert(std::pair<std::string, std::string(CParser::*)()>("R42", &CParser::R42));
    m_convolutions.insert(std::pair<std::string, std::string(CParser::*)()>("R43", &CParser::R43));
    m_convolutions.insert(std::pair<std::string, std::string(CParser::*)()>("R44", &CParser::R44));
    m_convolutions.insert(std::pair<std::string, std::string(CParser::*)()>("R45", &CParser::R45));
    m_convolutions.insert(std::pair<std::string, std::string(CParser::*)()>("R46", &CParser::R46));
    m_convolutions.insert(std::pair<std::string, std::string(CParser::*)()>("R47", &CParser::R47));
    m_convolutions.insert(std::pair<std::string, std::string(CParser::*)()>("R48", &CParser::R48));
    m_convolutions.insert(std::pair<std::string, std::string(CParser::*)()>("R49", &CParser::R49));
    m_convolutions.insert(std::pair<std::string, std::string(CParser::*)()>("R50", &CParser::R50));
    m_convolutions.insert(std::pair<std::string, std::string(CParser::*)()>("R51", &CParser::R51));
    m_convolutions.insert(std::pair<std::string, std::string(CParser::*)()>("R52", &CParser::R52));
    m_convolutions.insert(std::pair<std::string, std::string(CParser::*)()>("R53", &CParser::R53));
    m_convolutions.insert(std::pair<std::string, std::string(CParser::*)()>("R54", &CParser::R54));
    m_convolutions.insert(std::pair<std::string, std::string(CParser::*)()>("R55", &CParser::R55));
    m_convolutions.insert(std::pair<std::string, std::string(CParser::*)()>("R56", &CParser::R56));
    m_convolutions.insert(std::pair<std::string, std::string(CParser::*)()>("R57", &CParser::R57));
    m_convolutions.insert(std::pair<std::string, std::string(CParser::*)()>("R58", &CParser::R58));
    m_convolutions.insert(std::pair<std::string, std::string(CParser::*)()>("R59", &CParser::R59));
    m_convolutions.insert(std::pair<std::string, std::string(CParser::*)()>("R60", &CParser::R60));
    m_convolutions.insert(std::pair<std::string, std::string(CParser::*)()>("R61", &CParser::R61));
    m_convolutions.insert(std::pair<std::string, std::string(CParser::*)()>("R62", &CParser::R62));
    m_convolutions.insert(std::pair<std::string, std::string(CParser::*)()>("R63", &CParser::R63));
    m_convolutions.insert(std::pair<std::string, std::string(CParser::*)()>("R64", &CParser::R64));
    m_convolutions.insert(std::pair<std::string, std::string(CParser::*)()>("R65", &CParser::R65));
    m_convolutions.insert(std::pair<std::string, std::string(CParser::*)()>("R66", &CParser::R66));
}

bool CParser::IsMember(std::string const & element) const
{
    std::map<std::string, std::string(CParser::*)()>::const_iterator it;
    for (it = m_convolutions.begin(); it != m_convolutions.end(); ++it)
    {
        if (it->first == element)
        {
            return true;
        }
    }
    return false;
}

void CParser::RemoveElements(unsigned count)
{
    for (unsigned i = 0; i < count; i++)
    {
        m_rowsStack.pop();
    }
}

std::string CParser::R2()
{
    RemoveElements(2);
    return ColumnNames::PROGRAM;
}

std::string CParser::R3()
{
    RemoveElements(6);
    return ColumnNames::MAIN_BLOCK;
}

std::string CParser::R4()
{
    RemoveElements(2);
    return ColumnNames::CLASS_DELCS;
}

std::string CParser::R5()
{
    return ColumnNames::CLASS_DELCS;
}

std::string CParser::R6()
{
    RemoveElements(14);
    return ColumnNames::CLASS_DECL;
}

std::string CParser::R7()
{
    RemoveElements(2);
    return ColumnNames::VAR_DECLS;
}

std::string CParser::R8()
{
    return ColumnNames::VAR_DECLS;
}

std::string CParser::R9()
{
	if (!m_isFirstParse)
	{
		m_codeGeneratorManager.R9();
	}
    RemoveElements(3);
    return ColumnNames::VAR_DECL;
}

std::string CParser::R10()
{
    RemoveElements(2);
    return ColumnNames::METHOD_DECLS;
}

std::string CParser::R11()
{
    return ColumnNames::METHOD_DECLS;
}

std::string CParser::R12()
{
    RemoveElements(15);
    return ColumnNames::METHOD_DECL;
}

std::string CParser::R13()
{
    RemoveElements(3);
    return ColumnNames::FORMAL_LIST;
}

std::string CParser::R14()
{
    return ColumnNames::FORMAL_LIST;
}

std::string CParser::R15()
{
    RemoveElements(4);
    return ColumnNames::FORMAL_REST;
}

std::string CParser::R16()
{
    return ColumnNames::FORMAL_REST;
}

std::string CParser::R17()
{
    RemoveElements(1);
    return ColumnNames::TYPE;
}

std::string CParser::R18()
{
    RemoveElements(1);
    return ColumnNames::TYPE;
}

std::string CParser::R19()
{
    RemoveElements(1);
    return ColumnNames::STANDART_TYPE;
}

std::string CParser::R20()
{
    RemoveElements(1);
    return ColumnNames::STANDART_TYPE;
}

std::string CParser::R21()
{
    RemoveElements(2);
    return ColumnNames::STMTS;
}

std::string CParser::R22()
{
    return ColumnNames::STMTS;
}

std::string CParser::R23()
{
    RemoveElements(3);
    return ColumnNames::STMT;
}

std::string CParser::R24()
{
    RemoveElements(7);
    return ColumnNames::STMT;
}

std::string CParser::R25()
{
    RemoveElements(5);
    return ColumnNames::STMT;
}

std::string CParser::R26()
{
	if (!m_isFirstParse)
	{
		m_codeGeneratorManager.R26();
	}
    RemoveElements(5);
    return ColumnNames::STMT;
}

std::string CParser::R27()
{
    RemoveElements(4);
    return ColumnNames::STMT;
}

std::string CParser::R28()
{
	if (!m_isFirstParse)
	{
		m_codeGeneratorManager.R28();
	}
    RemoveElements(1);
    return ColumnNames::ASSIGNEMENT_RIGHT_PART;
}

std::string CParser::R29()
{
    RemoveElements(2);
    return ColumnNames::ASSIGNEMENT_RIGHT_PART;
}

std::string CParser::R57()
{
	if (!m_isFirstParse)
	{
		m_codeGeneratorManager.R57();
	}
    RemoveElements(4);
    return ColumnNames::NEW_ELEMENT;
}

std::string CParser::R58()
{
	if (!m_isFirstParse)
	{
		m_codeGeneratorManager.R58();
	}
    RemoveElements(4);
    return ColumnNames::NEW_ELEMENT;
}

std::string CParser::R30()
{
    RemoveElements(2);
    return ColumnNames::LOGIC_EXP;
}

std::string CParser::R61()
{
    RemoveElements(4);
    return ColumnNames::LOGIC_EXP;
}

std::string CParser::R31()
{
    RemoveElements(2);
    return ColumnNames::LOGIC_EXP_B;
}

std::string CParser::R32()
{
    return ColumnNames::LOGIC_EXP_B;
}

std::string CParser::R33()
{
	if (!m_isFirstParse)
	{
		m_codeGeneratorManager.R33();
	}
    RemoveElements(3);
    return ColumnNames::LOGIC_EXP_A;
}

std::string CParser::R34()
{
	if (!m_isFirstParse)
	{
		m_codeGeneratorManager.R34();
	}
    RemoveElements(1);
    return ColumnNames::LOGIC_EXP_A;
}

std::string CParser::R35()
{
	if (!m_isFirstParse)
	{
		m_codeGeneratorManager.R35();
	}
    RemoveElements(1);
    return ColumnNames::LOGIC_OP;
}

std::string CParser::R36()
{
	if (!m_isFirstParse)
	{
		m_codeGeneratorManager.R36();
	}
    RemoveElements(1);
    return ColumnNames::LOGIC_OP;
}

std::string CParser::R37()
{
	if (!m_isFirstParse)
	{
		m_codeGeneratorManager.R37();
	}
    RemoveElements(1);
    return ColumnNames::LOGIC_OP;
}

std::string CParser::R38()
{
	if (!m_isFirstParse)
	{
		m_codeGeneratorManager.R38();
	}
    RemoveElements(3);
    return ColumnNames::LOGIC_EXP_C;
}

std::string CParser::R39()
{
	if (!m_isFirstParse)
	{
		m_codeGeneratorManager.R39();
	}
    RemoveElements(1);
    return ColumnNames::LOGIC_EXP_C;
}

std::string CParser::R40()
{
	if (!m_isFirstParse)
	{
		m_codeGeneratorManager.R40();
	}
    RemoveElements(3);
    return ColumnNames::EXP;
}

std::string CParser::R41()
{
    RemoveElements(1);
    return ColumnNames::EXP;
}

std::string CParser::R42()
{
	if (!m_isFirstParse)
	{
		m_codeGeneratorManager.R42();
	}
    RemoveElements(2);
    return ColumnNames::EXP;
}

std::string CParser::R43()
{
	if (!m_isFirstParse)
	{
		m_codeGeneratorManager.R43();
	}
    RemoveElements(1);
    return ColumnNames::OP_A;
}

std::string CParser::R44()
{
	if (!m_isFirstParse)
	{
		m_codeGeneratorManager.R44();
	}
    RemoveElements(1);
    return ColumnNames::OP_A;
}

std::string CParser::R45()
{
	if (!m_isFirstParse)
	{
		m_codeGeneratorManager.R45();
	}
    RemoveElements(3);
    return ColumnNames::EXP_A;
}

std::string CParser::R46()
{
    RemoveElements(1);
    return ColumnNames::EXP_A;
}

std::string CParser::R59()
{
	if (!m_isFirstParse)
	{
		m_codeGeneratorManager.R59();
	}
    RemoveElements(1);
    return ColumnNames::OP_B;
}

std::string CParser::R60()
{
	if (!m_isFirstParse)
	{
		m_codeGeneratorManager.R60();
	}
    RemoveElements(1);
    return ColumnNames::OP_B;
}

std::string CParser::R47()
{
	if (!m_isFirstParse)
	{
		m_codeGeneratorManager.R47();
	}
    RemoveElements(1);
    return ColumnNames::EXP_C;
}

std::string CParser::R48()
{
    RemoveElements(1);
    return ColumnNames::EXP_C;
}

std::string CParser::R49()
{
    RemoveElements(3);
    return ColumnNames::EXP_C;
}

std::string CParser::R62()
{
    RemoveElements(6);
    return ColumnNames::EXP_C;
}

std::string CParser::R50()
{
	if (!m_isFirstParse)
	{
		m_codeGeneratorManager.R50();
	}
    RemoveElements(2);
    return ColumnNames::EXP_D;
}

std::string CParser::R51()
{
    RemoveElements(5);
    return ColumnNames::CALL_METHOD;
}

std::string CParser::R52()
{
    return ColumnNames::CALL_METHOD;
}

std::string CParser::R53()
{
    RemoveElements(2);
    return ColumnNames::EXP_LIST;
}

std::string CParser::R54()
{
    return ColumnNames::EXP_LIST;
}

std::string CParser::R55()
{
    RemoveElements(3);
    return ColumnNames::EXP_REST;
}

std::string CParser::R56()
{
    return ColumnNames::EXP_REST;
}

std::string CParser::R63()
{
    RemoveElements(1);
    return ColumnNames::ARG;
}

std::string CParser::R64()
{
	RemoveElements(1);
    return ColumnNames::ARG;
}

std::string CParser::R65()
{
    RemoveElements(1);
    return ColumnNames::LOGIC_EXP_ARG;
}

std::string CParser::R66()
{
	RemoveElements(1);
	return ColumnNames::LOGIC_EXP_ARG;
}